/**
 * @Title: AuthController.java
 * @Package com.kaver.web.controller
 * @author roc
 * @date Jul 23, 2021 11:38:34 AM
 * @version V1.0
 * @copyright kaver
 */
package com.kaver.sso.web.controller.page;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.util.UriComponentsBuilder;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.kaver.sso.config.CommonConfig;
import com.kaver.sso.config.Constant;
import com.kaver.sso.dao.po.SsoApp;
import com.kaver.sso.dao.po.SsoRights;
import com.kaver.sso.dao.service.SsoAppDao;
import com.kaver.sso.dao.service.SsoRoleRightsDao;
import com.kaver.sso.def.req.LoginReq;
import com.kaver.sso.def.resp.User;
import com.kaver.sso.helper.SsoUserHolder;
import com.kaver.sso.helper.UnAuth;
import com.kaver.sso.service.UserService;
import com.kaver.sso.utils.CookieUtil;

/**
 * @ClassName: AuthController
 * @Description: 基于cookie的认证方式
 * @author roc
 * @date Jul 23, 2021 11:38:34 AM
 * 
 */
@Controller
public class AuthController {
	@Autowired
	SsoAppDao ssoAppDao;
	@Autowired
	CommonConfig commonConfig;
	@Autowired
	UserService userService;
	@Autowired
	RedisTemplate<String, Object> redisTemplate;
	@Autowired
	SsoRoleRightsDao ssoRoleRightsDao;

	/**
	 * 登陆页
	 */
	@UnAuth
	@RequestMapping("/")
	public String index(Model model, String from) {
		model.addAttribute("publicKey", Constant.publicKey);
		model.addAttribute("from", from);
		User user = SsoUserHolder.get();
		if (user != null) {
		    if (StringUtils.isNotBlank(from)) {
		        boolean isogeny = this.isEqDomain(from);
		        if (isogeny) {
		            return "redirect:" + from; 
		        } else {
		            String ticket = userService.getTicket(user);
		            String url = UriComponentsBuilder.fromHttpUrl(from).queryParam("ticket", ticket).build().toString();
		            return "redirect:" + url; 
		        }
		    } else {
		        return "redirect:/index";
		    }
		}
		return "login";
	}

	/**
	 * 登陆
	 */
	@UnAuth
	@RequestMapping("/login")
	public String login(Model model, HttpServletResponse response, LoginReq req) {
		model.addAttribute("publicKey", Constant.publicKey);
		model.addAttribute("userAcc", req.getUserAcc());
		model.addAttribute("from", req.getFrom());
		model.addAttribute("ifRemember", req.isIfRemember());
		if (StringUtils.isBlank(req.getUserAcc())) {
			model.addAttribute("errorMsg", "请输入帐号");
			return "login";
		}
		if (StringUtils.isBlank(req.getPwd())) {
			model.addAttribute("errorMsg", "请输入密码");
			return "login";
		}
		Boolean canLogin = userService.canLogin(req.getUserAcc());
		if (canLogin == null) {
			model.addAttribute("errorMsg", "帐号或者密码错误");
			return "login";
		}
		if (!canLogin) {
			model.addAttribute("errorMsg", "当前账户已被锁定，请联系管理人员解锁");
			return "login";
		}
		boolean isogeny = this.isEqDomain(req.getFrom());
		String token = userService.login(req.getUserAcc(), req.getPwd(), isogeny, req.isIfRemember());
		if (token == null) {
			model.addAttribute("errorMsg", "帐号或者密码错误");
			return "login";
		}
		if (StringUtils.isBlank(req.getFrom())) {
			CookieUtil.set(response, Constant.cookie_session_key, token, commonConfig.getDomain(), req.isIfRemember());
			return "redirect:/index";
		}
		if (isogeny) {
			CookieUtil.set(response, Constant.cookie_session_key, token, commonConfig.getDomain(), req.isIfRemember());
		} else {
			try {
				req.setFrom(UriComponentsBuilder.fromHttpUrl(req.getFrom()).queryParam("ticket", token).build().toString());
			} catch (Exception e) {
				
			}
		}
		return "redirect:" + req.getFrom();
	}
	private boolean isEqDomain(String from) {
		try {
			if (StringUtils.isBlank(from)) {
				return true;
			}
			Pattern p = Pattern.compile("(?<=http://|\\.)[^.]*?\\.(com|cn|net|org|biz|info|cc|tv)",
					Pattern.CASE_INSENSITIVE);
			Matcher matcher = p.matcher(from);
			matcher.find();
			String domain = matcher.group();
			if (commonConfig.getDomain().equals(domain)) {
				return true;
			}
		} catch (Exception e) {
		}
		return false;
	}

	/**
	 * 退出登陆
	 */
	@UnAuth
	@RequestMapping("/logout")
	public String logout(Model model, HttpServletRequest request, HttpServletResponse response) {
		String token = CookieUtil.getValue(request, Constant.cookie_session_key);
		if (token != null) {
			redisTemplate.delete(token);
		}
		CookieUtil.remove(request,response, commonConfig.getDomain(), Constant.cookie_session_key);
		return "redirect:/";
	}

	/**
	 * 应用页
	 */
	@RequestMapping("/index")
	public String index(Model model, HttpServletRequest request) {
	    User user = SsoUserHolder.get();
	    // 如果是初始密码直接跳到修改密码页面
	    if (userService.isUserInitPwd(user.getUserId())) {
	        return "redirect:/changePwd";
	    }
		SsoApp query = new SsoApp();
		query.setIsShow(true);
		QueryWrapper<SsoApp> queryWrapper = new QueryWrapper<SsoApp>(query);
		queryWrapper.orderByAsc("sorts");
		List<SsoApp> apps = new ArrayList<SsoApp>();
		List<SsoRights> rights = ssoRoleRightsDao.queryUserRights(user.getUserId(), commonConfig.getGroupId());
		if (!CollectionUtils.isEmpty(rights)) {
			Optional<SsoRights> optional = rights.stream().filter(it -> "appList".equals(it.getRightIdentifier()))
					.findFirst();
			if (optional.isPresent()) {
				SsoRights appListRight = optional.get();
				List<String> ids = rights.stream().filter(it -> appListRight.getId().equals(it.getParentId()))
						.map(it -> it.getRightIdentifier()).collect(Collectors.toList());
				List<SsoApp> ssoApps = ssoAppDao.list(queryWrapper);
				for (SsoApp app : ssoApps) {
					if (ids.contains(app.getId().toString())) {
						apps.add(app);
					}
				}
			}
		}
		model.addAttribute("apps", apps);
		model.addAttribute("user", SsoUserHolder.get());
		return "index";
	}

	/**
	 * 添加用户
	 */
	@RequestMapping("/addUser")
	public String addUser(Model model, HttpServletRequest request) {
		return "addUser";
	}

	/**
	 * 修改密码
	 */
	@RequestMapping("/changePwd")
	public String changePwd(Model model, HttpServletRequest request) {
		model.addAttribute("publicKey", Constant.publicKey);
		return "changePwd";
	}
}
